package db

import (
	"fmt"
	"time"

	"github.com/yourusername/rss-reader-ai/internal/config"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
)

// =====================================================
// Database 数据库连接封装
// =====================================================

// Database 数据库实例
type Database struct {
	DB *gorm.DB
}

// =====================================================
// InitDB - 初始化数据库连接
// =====================================================

// InitDB 初始化数据库连接
// 参数:
//   - cfg: 配置对象
// 返回:
//   - *Database: 数据库实例
//   - error: 错误信息
func InitDB(cfg *config.Config) (*Database, error) {
	// 1. 构建 DSN (Data Source Name)
	dsn := cfg.Database.GetDSN()

	// 2. 配置 GORM 日志级别
	var logLevel logger.LogLevel
	switch cfg.Log.Level {
	case "debug":
		logLevel = logger.Info // 调试模式显示所有 SQL
	case "info":
		logLevel = logger.Warn // 只显示慢查询和错误
	case "warn", "error":
		logLevel = logger.Error // 只显示错误
	default:
		logLevel = logger.Silent // 不显示日志
	}

	// 3. 打开数据库连接
	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
		Logger: logger.Default.LogMode(logLevel),
		// 禁用自动创建外键约束(我们在 SQL 中手动管理)
		DisableForeignKeyConstraintWhenMigrating: true,
	})

	if err != nil {
		return nil, fmt.Errorf("连接数据库失败: %w", err)
	}

	// 4. 获取底层的 *sql.DB 对象,用于配置连接池
	sqlDB, err := db.DB()
	if err != nil {
		return nil, fmt.Errorf("获取数据库实例失败: %w", err)
	}

	// 5. 配置连接池参数
	sqlDB.SetMaxIdleConns(cfg.Database.MaxIdleConns)                         // 最大空闲连接数
	sqlDB.SetMaxOpenConns(cfg.Database.MaxOpenConns)                         // 最大打开连接数
	sqlDB.SetConnMaxLifetime(time.Duration(cfg.Database.ConnMaxLifetime) * time.Second) // 连接最大存活时间

	// 6. 测试连接
	if err := sqlDB.Ping(); err != nil {
		return nil, fmt.Errorf("数据库连接测试失败: %w", err)
	}

	return &Database{DB: db}, nil
}

// =====================================================
// Close - 关闭数据库连接
// =====================================================

// Close 关闭数据库连接
func (d *Database) Close() error {
	sqlDB, err := d.DB.DB()
	if err != nil {
		return err
	}
	return sqlDB.Close()
}
